unit settings;

{$mode objfpc}
{$H+}

interface

uses
  classes, sysutils, gtk2, glib2, gdk2, common;
  
type
  TProfileDialog = class;
  
  TSettingUp = class(TObject)
    private
      FOwner : PGtkWindow;
      FFilePath : string;
      FList   : TList;
      FDialog : TProfileDialog;
      FModified : boolean;
      FHasError : boolean;
      function Get(Index: Integer) : TProcessInfo;
      function GetCount : integer;
    public
      constructor Create(TheWindow : PGtkWindow);
      destructor  Destroy; override;
      function    AddProfile : TProcessInfo;
      function    EditProfile(TheInfo : TProcessInfo) : boolean;
      function    DeleteProfile(TheInfo : TProcessInfo) : boolean;
      property    Modified : boolean read FModified;
      property    HasError : boolean read FHasError;
      property    Items[Index:integer] : TProcessInfo read Get;
      property    Count : integer read GetCount;
  end;//TSettingUp
  //-------------------------
  TProfileDialog = class(TObject)
    private
      FOwner  : PGtkWindow;
      FDialog : PGtkWidget;
      FEntry1 : PGtkWidget;
      FEntry2 : PGtkWidget;
      FEntry3 : PGtkWidget;
      FEntry4 : PGtkWidget;
      FEntry5 : PGtkWidget;
      FServer : string;
      FUser   : string;
      FRPort  : string;
      FLPort  : string;
      FDescript : string;
      function    DoRun : boolean;
    public
      constructor Create(TheWindow : PGtkWindow);
      destructor  Destroy; override;
      function    Run : boolean;
      function    Run(TheInfo : TProcessInfo) : boolean;
      property    Server : string read FServer;
      property    User : string read FUser;
      property    RPort : string read FRPort;
      property    LPort : string read FLPort;
      property    Descript : string read FDescript;
  end;//TProfileDialog
  
  
implementation
  
  
  constructor TSettingUp.Create(TheWindow : PGtkWindow);
  var
    f : text;
    s : string;
    OneInfo : TProcessInfo;
  begin
    inherited Create;
    
    FOwner := TheWindow;
    FList := TList.Create;
    FModified := false;
    FHasError := false;
    
    FFilePath := GetEnvironmentVariable('HOME') + '/.config';
    if not FileExists(FFilePath) then begin
      Mkdir(FFilePath);
    end;
    FFilePath := FFilePath + '/sshtunnel';
    if not FileExists(FFilePath) then begin
      Mkdir(FFilePath);
    end;
    FFilePath := FFilePath + '/config';
    Assign(f, FFilePath);
    if not FileExists(FFilePath) then begin
      ReWrite(f);
    end else begin
      ReSet(f);
      while not eof(f) do begin
        Readln(f, s);
        s := trim(s);
        if (s='') or (s[1]='#') then continue;
        
        try
          OneInfo := TProcessInfo.Create(s);
          FList.Add(OneInfo);
        except
          on e : Exception do begin
            FHasError := true;
          end;
        end;
      end;//while
    end;
    Close(f);
    
    FDialog := TProfileDialog.Create(FOwner);
  end;//TSettingUp.Create
  //-------------------------
  destructor TSettingUp.Destroy;
  var
    i : integer;
    OneInfo : TProcessInfo;
  begin
    FreeAndNil(FDialog);
    for i:=0 to FList.Count-1 do begin
      OneInfo := TProcessInfo(FList.Items[i]);
      FreeAndNil(OneInfo);
    end;//for i
    if Assigned(FList) then FreeAndNil(FList);
    inherited Destroy;
  end;//TSettingUp.Destroy
  //-------------------------
  function TSettingUp.Get(Index: Integer) : TProcessInfo;
  begin
    Result := TProcessInfo(FList.Items[Index]);
  end;//TSettingUp.Get
  //-------------------------
  function TSettingUp.GetCount : integer;
  begin
    Result := FList.Count;
  end;//TSettingUp.GetCount
  //-------------------------
  function TSettingUp.AddProfile : TProcessInfo;
  var
    f : text;
  begin
    Result := nil;
    if FDialog.Run then begin
      Result := TProcessInfo.Create(FDialog.User, FDialog.Server, FDialog.Descript, StrToInt(FDialog.RPort), StrToInt(FDialog.LPort));
      //append to the profile file
      Assign(f, FFilePath);
      Append(f);
      writeln(f, FDialog.Server, ',', FDialog.User, ',', StrToInt(FDialog.RPort), ',', StrToInt(FDialog.LPort), ',', FDialog.Descript);
      Close(f);
      FList.Add(Result);
    end;
  end;//TSettingUp.AddProfile
  //-------------------------
  function TSettingUp.EditProfile(TheInfo : TProcessInfo) : boolean;
  var
    f : text;
    i : integer;
    OneInfo : TProcessInfo;
  begin
    Result := false;
    if FDialog.Run(TheInfo) then begin
      Result := true;
      TheInfo.Server := FDialog.Server;
      TheInfo.User   := FDialog.User;
      TheInfo.Descript   := FDialog.Descript;
      TheInfo.RPort  := StrToInt(FDialog.RPort);
      TheInfo.LPort  := StrToInt(FDialog.LPort);
      //rewrite to the profile file
      Assign(f, FFilePath);
      ReWrite(f);
      for i:=0 to FList.Count-1 do begin
        OneInfo := TProcessInfo(FList.Items[i]);
        writeln(f, OneInfo.Server, ',', OneInfo.User, ',', OneInfo.RPort, ',', OneInfo.LPort, ',', OneInfo.Descript);
      end;
      Close(f);
    end;
  end;//TSettingUp.EditProfile
  //-------------------------
  function TSettingUp.DeleteProfile(TheInfo : TProcessInfo) : boolean;
  var
    f : text;
    i : integer;
    OneInfo : TProcessInfo;
  begin
    Result := false;
    FList.Remove(TheInfo);
    //rewrite to the profile file
    Assign(f, FFilePath);
    ReWrite(f);
    for i:=0 to FList.Count-1 do begin
      OneInfo := TProcessInfo(FList.Items[i]);
      writeln(f, OneInfo.Server, ',', OneInfo.User, ',', OneInfo.RPort, ',', OneInfo.LPort, ',', OneInfo.Descript);
    end;
    Close(f);
    Result := true;
  end;//TSettingUp.DeleteProfile
  
  
  constructor TProfileDialog.Create(TheWindow : PGtkWindow);
  var
    table  : PGtkWidget;
    labels : PGtkWidget;
  begin
    inherited Create;
    FOwner := TheWindow;
    FServer := '';
    FUser   := '';
    FRPort  := '';
    FLPort  := '';
    FDescript := '';
    
    FDialog := gtk_dialog_new;
    gtk_window_set_position(PGtkWindow(FDialog),GTK_WIN_POS_CENTER_ALWAYS);
    gtk_window_set_destroy_with_parent(PGtkWindow(FDialog), false);
    gtk_window_set_modal(PGtkWindow(FDialog), true);
    gtk_window_set_position(PGtkWindow(FDialog), GTK_WIN_POS_CENTER);
    gtk_window_set_transient_for(PGtkWindow(FDialog), PGtkWindow(FOwner));
    gtk_dialog_add_button(PGtkDialog(FDialog), 'Yes', GTK_RESPONSE_YES);
    gtk_dialog_add_button(PGtkDialog(FDialog), 'Cancel', GTK_RESPONSE_CANCEL);
    
    table := gtk_table_new(5, 2, true);
    
    labels := gtk_label_new('Server :');
    gtk_label_set_justify(PGtkLabel(labels), GTK_JUSTIFY_RIGHT);
    gtk_table_attach(PGtkTable(table), labels, 0, 1, 0, 1, GTK_EXPAND and GTK_FILL, GTK_EXPAND and GTK_FILL, 0, 0);
    labels := gtk_label_new('User :');
    gtk_label_set_justify(PGtkLabel(labels), GTK_JUSTIFY_RIGHT);
    gtk_table_attach(PGtkTable(table), labels, 0, 1, 1, 2, GTK_EXPAND and GTK_FILL, GTK_EXPAND and GTK_FILL, 0, 0);
    labels := gtk_label_new('Remote Port :');
    gtk_label_set_justify(PGtkLabel(labels), GTK_JUSTIFY_RIGHT);
    gtk_table_attach(PGtkTable(table), labels, 0, 1, 2, 3, GTK_EXPAND and GTK_FILL, GTK_EXPAND and GTK_FILL, 0, 0);
    labels := gtk_label_new('Local Port :');
    gtk_label_set_justify(PGtkLabel(labels), GTK_JUSTIFY_RIGHT);
    gtk_table_attach(PGtkTable(table), labels, 0, 1, 3, 4, GTK_EXPAND and GTK_FILL, GTK_EXPAND and GTK_FILL, 0, 0);
    labels := gtk_label_new('Description :');
    gtk_label_set_justify(PGtkLabel(labels), GTK_JUSTIFY_RIGHT);
    gtk_table_attach(PGtkTable(table), labels, 0, 1, 4, 5, GTK_EXPAND and GTK_FILL, GTK_EXPAND and GTK_FILL, 0, 0);
    
    FEntry1 := gtk_entry_new;
    gtk_table_attach(PGtkTable(table), FEntry1, 1, 2, 0, 1, GTK_EXPAND and GTK_FILL, GTK_EXPAND and GTK_FILL, 0, 0);
    FEntry2 := gtk_entry_new;
    gtk_table_attach(PGtkTable(table), FEntry2, 1, 2, 1, 2, GTK_EXPAND and GTK_FILL, GTK_EXPAND and GTK_FILL, 0, 0);
    FEntry3 := gtk_entry_new;
    gtk_table_attach(PGtkTable(table), FEntry3, 1, 2, 2, 3, GTK_EXPAND and GTK_FILL, GTK_EXPAND and GTK_FILL, 0, 0);
    FEntry4 := gtk_entry_new;
    gtk_table_attach(PGtkTable(table), FEntry4, 1, 2, 3, 4, GTK_EXPAND and GTK_FILL, GTK_EXPAND and GTK_FILL, 0, 0);
    FEntry5 := gtk_entry_new;
    gtk_table_attach(PGtkTable(table), FEntry5, 1, 2, 4, 5, GTK_EXPAND and GTK_FILL, GTK_EXPAND and GTK_FILL, 0, 0);
    
    gtk_box_pack_start(PGtkBox(PGtkDialog(FDialog)^.vbox), table, true, true, 5);
    gtk_widget_show_all(table);
  end;//TProfileDialog.Create
  //-------------------------
  destructor TProfileDialog.Destroy;
  begin
    gtk_widget_destroy(FDialog);
    inherited Destroy;
  end;//TProfileDialog.Destroy
  //-------------------------
  function TProfileDialog.Run : boolean;
  begin
    FServer := '';
    FUser   := '';
    FRPort  := '';
    FLPort  := '';
    FDescript := '';
    Result := DoRun;
  end;//TProfileDialog.Run
  //-------------------------
  function TProfileDialog.Run(TheInfo : TProcessInfo) : boolean;
  begin
    FServer := TheInfo.Server;
    FUser   := TheInfo.User;
    FDescript := TheInfo.Descript;
    FRPort  := IntToStr(TheInfo.RPort);
    FLPort  := IntToStr(TheInfo.LPort);
    Result := DoRun;
  end;//TProfileDialog.Run
  //-------------------------
  function TProfileDialog.DoRun : boolean;
  var
    retval : gint;
    n : integer;
  begin
    Result := false;
    gtk_entry_set_text(PGtkEntry(FEntry1), PGChar(FServer));
    gtk_entry_set_text(PGtkEntry(FEntry2), PGChar(FUser));
    gtk_entry_set_text(PGtkEntry(FEntry3), PGChar(FRPort));
    gtk_entry_set_text(PGtkEntry(FEntry4), PGChar(FLPort));
    gtk_entry_set_text(PGtkEntry(FEntry5), PGChar(FDescript));
    while true do begin
      retval := gtk_dialog_run(PGtkDialog(FDialog));
      
      if retval=GTK_RESPONSE_YES then begin
        try
          FServer := trim(gtk_entry_get_text(PGtkEntry(FEntry1)));
          if FServer='' then continue;
          FUser   := trim(gtk_entry_get_text(PGtkEntry(FEntry2)));
          if FUser='' then continue;
          FDescript := trim(gtk_entry_get_text(PGtkEntry(FEntry5)));
          if FDescript='' then continue;
          FRPort  := gtk_entry_get_text(PGtkEntry(FEntry3));
          n := StrToInt(FRPort);
          FLPort  := gtk_entry_get_text(PGtkEntry(FEntry4));
          n := StrToInt(FLPort);
          Result := true;
          break;
        except
        end;
      end else begin
        break;
      end;
    end;//while
    gtk_widget_hide(FDialog);
  end;//TProfileDialog.Run
  
  
initialization



finalization



end.//unit settings

